#pragma once

#include "math/pch.h"

namespace Math
{
	struct Transform
	{
		static glm::vec3 Xup();
		static glm::vec3 Zup();
		static glm::vec3 Yup();

		glm::vec3 position;
		glm::vec3 rotation;
		glm::vec3 scale;

		Transform();
		glm::vec3 GetRight() const;
		glm::vec3 GetForward() const;
		glm::vec3 GetUp() const;
		 
		glm::mat4 GetViewMatrix() const;
		glm::mat4 GetWorld() const;

		glm::mat4 GetPosRotMatrix() const;

		Transform(const glm::vec3 &pos, const glm::quat &rot, const glm::vec3 &scale);
		
		void CreateFrom(const glm::mat4 &local);
		void RotateX(float d);
		void RotateY(float d);
		void RotateZ(float d);
		void Rotate(glm::vec3);

		void SetPosition(const glm::vec3 &pos);
		void SetRotation(const glm::quat &q);
		void SetScale(const glm::vec3& scale);

		void Scale(float d);

		void BackAt(glm::vec3 pos, glm::vec3 worldUp = glm::vec3(0.0f, 1.0f, 0.0f));
		void LookAt(glm::vec3 pos, glm::vec3 worldUp = glm::vec3(0.0f, 1.0f, 0.0f));

		glm::mat4 GetRotationMatrix() const;

		glm::quat GetRoatationQuat() const;

		void Move(float dist, glm::vec3 f);
		void Translate(float dist);
		void MoveRight(float dist);

		void Scale(glm::vec3 o, float d);
		glm::vec3 GetPosXZ() const;
		glm::vec3 GetPosYZ() const;
		glm::vec3 GetPosXY() const;

		float GetToXZSq();

		glm::vec3 PlusScale() const
		{
			glm::vec3 s2 = scale;
			float x = s2.x;
			float y = s2.y;
			float z = s2.z;

			if (x < 0) x *= -1;
			if (y < 0)y *= -1;
			if (z < 0)z *= -1;

			return glm::vec3(x, y, z);
		}
		float MaxScaleAxis() const
		{
			glm::vec3 s2 = PlusScale();
			return glm::max(glm::max(s2.x, s2.y), s2.z);;
		}
	};

	inline Transform Slerp(const Transform& t1, const Transform& t2, float axis)
	{
		Transform res;
		res.position = glm::mix(t1.position, t2.position, axis);
		res.rotation = glm::mix(t1.rotation, t2.rotation, axis);
		res.scale = glm::mix(t1.scale, t2.scale, axis);

		return res;
	}


}
